package model;

//file handlers
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.File;
//xml handlers
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
//general utility classes
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;


public class AcolyteCard
{
  //all the properties of a given card
  private Properties cardProperties;
  //the game zone this card is in
  private AcolyteZone myZone;
  
  
  //create a card given the filename of it
  public AcolyteCard(String filename)
  {
    cardProperties = new Properties();
    
    try
    {
      setup(filename);
    }
    catch(FileNotFoundException e)
    {
      //if file not found try removing the spaces and adding .xml because this may be the name of the card
      filename = filename.replace(" ", "");
      filename += ".xml";
      try
      {
        setup(filename);
      }
      catch(FileNotFoundException ex)
      {
        e.printStackTrace();
        //TODO popup error about missing file
      }
      catch(XMLStreamException ex)
      {
        e.printStackTrace();
        //TODO popup error about malformed card file
      }
    }
    catch(XMLStreamException e)
    {
      System.out.println(filename);
      e.printStackTrace();
      //TODO popup error about malformed card file
    }
  }
  
  
  //set up the card from a file
  private void setup(String filename) throws XMLStreamException, FileNotFoundException
  {
      //grab the file and attach it to an XML reader
      FileInputStream in = new FileInputStream("cards/" + filename);
      XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(in);
      cardProperties.setProperty("filename", filename);
            
      //skip anything at the begining until the card tag
      while("card" != reader.getLocalName()) reader.nextTag();
      
      //loop while there is more in the file to read
      while(reader.hasNext())
      {
        //jump through tags on the card
        reader.nextTag();
        
        //only go through this for opening tags so we get no duplication
        if(reader.isStartElement())
        {
          //tags should always value at least 1 attribute value="..."
          //otherwise we pretty much ignore the tag
          if(0 < reader.getAttributeCount())
          {
            String attribute = reader.getLocalName();
            String value = reader.getAttributeValue(0);
            //if there is already a value for this property, append it to this instead of
            //replacing the old value.
            if(null != cardProperties.getProperty(attribute))
            {
              value += "|" + cardProperties.getProperty(attribute);
            }
            cardProperties.setProperty(attribute, value);
          }
        }
        //if this is true we got to the end of the card and should break out
        else if("card" == reader.getLocalName())
        {
          break;
        }
      }
  }
  
  //cards are equal if their names are the same
  public boolean equals(Object toCompare)
  {
    AcolyteCard compare = (AcolyteCard) toCompare;
    return this.get("name").equals(compare.get("name"));
  }
  
  public String toString()
  {
    return toXML();
  }
  
  //Generate XML to save a card
  //TODO make this method more generic
  public String toXML()
  {
    String result="";
    
    result = "<card>\n";
    result += "\t<name value='";
    result += cardProperties.getProperty("name", "");
    result += "'/>\n";
    
    String cost = cardProperties.getProperty("cost", "");
    if("" != cost)
    {
      result +="\t<cost value='";
      result += cost;
      result += "'/>\n";
    }
    
    //result +="\nType:\t\t";
    String supertype = cardProperties.getProperty("supertype", "");
    if("" != supertype)
    {
      result += "\t<supertype value='" + supertype + "'/>\n";
    }
    StringTokenizer st = new StringTokenizer(cardProperties.getProperty("type", ""), "|");
    while(st.hasMoreTokens())
    {
      result += "\t<type value ='" + st.nextToken() + "'/>\n";
    }
    //result += cardProperties.getProperty("type", "").replace('|', ' ');
    st =  new StringTokenizer(cardProperties.getProperty("subtype", ""), "|");
    while(st.hasMoreTokens())
    {
      result += "\t<subtype value ='" + st.nextToken() + "'/>\n";
    }
    
    //result +="\nPow/Tgh:\t\t";
    String power = cardProperties.getProperty("power", "");
    if("" != power)
    {
      result += "\t<power value='" + power + "'/>";
    }
    String toughness = cardProperties.getProperty("toughness", "");
    if("" != toughness)
    {
      result += "\t<toughness value='" + toughness + "'/>";
    }
    result +="\t<rulestext>\n";
    st = new StringTokenizer(cardProperties.getProperty("ability", ""), "|");
    while(st.hasMoreTokens())
    {
      result += "\t\t<ability value='" + st.nextToken() + "'/>\n";
    }
    result +="\t</rulestext>\n";
    
    //TODO: add flavortext XML
    
    result += "\t<set value='";
    result += cardProperties.getProperty("set", "");
    result += "'/>\n";
    
    result += "\t<rarity='";
    result += cardProperties.getProperty("rarity", "");
    result += "'/>\n";
    result += "</card>";
    return result;
  }
  
  //returns a property of the String or an empty string if the property is not set
  public String get(String property)
  {
    return cardProperties.getProperty(property, "");
  }
  
  public void set(String property, String value)
  {
    cardProperties.setProperty(property, value);
  }
  
  public AcolyteZone getZone()
  {
    return myZone;
  }
  
  public void setZone(AcolyteZone newZone)
  {
    myZone = newZone;
  }
  
  //returns a list of all cards in the cards folder
  public static List<AcolyteCard> cardList(String subFolder, boolean recursive)
  {
    File folder = new File("cards/" + subFolder);
    File[] cardList = folder.listFiles();
    List<AcolyteCard> cards = new ArrayList<AcolyteCard>();
    
    
    for (int i = 0; i < cardList.length; i++) {
      if (cardList[i].isFile()) {
        cards.add(new AcolyteCard(cardList[i].getName()));
        //System.out.println("File " + cardList[i].getName());
      }
      else if(recursive)//recursive calls to go deeper
      {
        String recursiveFolder = subFolder + cardList[i].getName() + "/";
        List<AcolyteCard> temp = cardList(recursiveFolder, true);
        //TODO add temp to cards
        cards.addAll(temp);
      }
    }
    return cards;
  }
  
  public static List<AcolyteCard> cardList()
  {
    return cardList("", false);
  }
  
  public static void main(String[] args)
  {
    List<AcolyteCard> collection = AcolyteCard.cardList();
    for(AcolyteCard ac : collection)
    {
      System.out.println(ac.get("name"));
      //new cardTemplate().show(ac);
      //ac.show();
    }
    //AcolyteCard card = new AcolyteCard("cardTest.xml");
    //card.show();
    //System.out.println(card);
    return;
    
  }
}